package com.wxxymakers.grademark.config;

import com.wxxymakers.grademark.config.realm.WxUserRealm;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @AUTHOR soft
 * @DATE 2018/10/26 16:37
 * @DESCRIBE Shiro配置
 */
@Configuration
public class ShiroConfig {

    /**
     * shiro安全管理器bean
     *
     * @param realm 自定义的realm
     */
    @Bean("securityManager")
    public WebSecurityManager getSecurityManager(@Qualifier("authrcRealm") Realm realm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        securityManager.setCacheManager(new MemoryConstrainedCacheManager());
        CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
        rememberMeManager.getCookie().setMaxAge(7 * 3600 * 24); // 保存七天
        securityManager.setRememberMeManager(rememberMeManager);
        return securityManager;
    }

    /**
     * 自定义的realm
     *
     * @param md5Matcher 凭证验证器
     */
    @Bean("authrcRealm")
    public Realm getWxUserRealm(CredentialsMatcher md5Matcher, WxUserRealm realm ) {
        realm.setCredentialsMatcher(md5Matcher);
        return realm;
    }

    /**
     * md5凭证验证器
     */
    @Bean("md5Matcher")
    public CredentialsMatcher getCredentialsMatcher() {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");
        matcher.setHashIterations(101);
        return matcher;
    }

    /**
     * 注解支持的前提
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
    /**
     * shiro注解支持
     * @param securityManager 安全管理器
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(WebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    /**
     * Shiro过滤器
     * @param securityManager 安全管理器
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilter(WebSecurityManager securityManager) {
        ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
        filter.setSecurityManager(securityManager);
        filter.setLoginUrl("/login");
        filter.setSuccessUrl("/");
        filter.setUnauthorizedUrl("/unauth");

        Map<String, Filter> filterMap = new HashMap<>();
        filterMap.put("token", new TokenFilter());
        filter.setFilters(filterMap);

        Map<String, String> map = new LinkedHashMap<>();
        map.put("/verify", "anon");
        map.put("/login", "anon");
        map.put("/register", "anon");
        map.put("/logout", "logout");
        map.put("/unauth", "anon");
        map.put("/none/**", "anon");
        map.put("/user/none/**", "anon");
        map.put("/static/**", "anon");
        map.put("/dept/list", "anon");
        map.put("/duty/list", "anon");
        map.put("/collage/list", "anon");
        map.put("/**", "token");

        filter.setFilterChainDefinitionMap(map);
        return filter;
    }
}
